/**
 * Copyright (C) 2009 Ignasi Fosch Alonso
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
 * details.
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * You can reach me by mail at natx@y10k.ws
 * You can reach him by paper mail at:
 * C. LLEIDA, 41-43, 3r 1a
 * El Prat de Llobregat 08820
 * Barcelona, SPAIN
 */
package ws.y10k.vsmanager;

import java.rmi.RemoteException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.ExpandBar;
import org.eclipse.swt.widgets.ExpandItem;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.TreeItem;

import com.vmware.vim25.FileFault;
import com.vmware.vim25.InsufficientResourcesFault;
import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.InvalidState;
import com.vmware.vim25.RuntimeFault;
import com.vmware.vim25.TaskInProgress;
import com.vmware.vim25.VmConfigFault;

import ws.y10k.vi.DatastoreNotFoundException;
import ws.y10k.vi.Guest;
import ws.y10k.vi.Host;
import ws.y10k.vi.NetworkNotFoundException;
import ws.y10k.vi.TreeLeaf;

/**
 * @author natx
 *
 */
public class HostsTreeSelectionListener implements Listener {

	/* (non-Javadoc)
	 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
	 */
	@Override
	public void handleEvent(Event arg0) {
		// TODO i18n
		TreeLeaf leaf = (TreeLeaf)((TreeItem)arg0.item).getData();
		CTabItem tbiLeaf = VSManager.addTabItem(leaf.getName());
		if ( ((TreeItem) arg0.item).getData() instanceof Host ) {
			
			final Host host = (Host)leaf;
			
			Composite cmpHost = new Composite(tbiLeaf.getParent(),SWT.NONE);
			cmpHost.setSize(tbiLeaf.getParent().getBounds().width - 10, tbiLeaf.getParent().getBounds().height - 10);
			GridLayout lytGrid = new GridLayout();
			lytGrid.numColumns = 2;
			cmpHost.setLayout(lytGrid);
			
			ExpandBar barSystem = new ExpandBar(cmpHost, SWT.NONE);
			GridData grd = new GridData();
			grd.widthHint = cmpHost.getBounds().width / 2;
			grd.heightHint = cmpHost.getBounds().height / 2;
			grd.verticalAlignment = SWT.TOP;
			barSystem.setLayoutData(grd);
			
			Composite cmpHardware = new Composite(barSystem, SWT.NONE);
			lytGrid = new GridLayout ();
			lytGrid.marginLeft = 30;
			lytGrid.marginTop = lytGrid.marginRight = lytGrid.marginBottom = 2;
			cmpHardware.setLayout(lytGrid);

			new Label(cmpHardware,SWT.WRAP).setText("Computer : " + host.getComputer());
			new Label(cmpHardware,SWT.WRAP).setText("BIOS Information : " + host.getBIOSInfo());
			new Label(cmpHardware,SWT.WRAP).setText("CPU : " + host.getCPU());
			new Label(cmpHardware,SWT.WRAP).setText("Memory : " + host.getMemory());
			
			ExpandItem itHardwareInfo = new ExpandItem (barSystem, SWT.NONE, 0);
			itHardwareInfo.setText("Hardware Information");
			itHardwareInfo.setHeight(cmpHardware.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			itHardwareInfo.setControl(cmpHardware);
			
			Composite cmpSoftware = new Composite(barSystem, SWT.NONE);
			lytGrid = new GridLayout ();
			lytGrid.marginLeft = 30;
			lytGrid.marginTop = lytGrid.marginRight = lytGrid.marginBottom = 2;
			cmpSoftware.setLayout(lytGrid);
			
			new Label(cmpSoftware,SWT.WRAP).setText("VMware Software : " + host.getSoftware());
			new Label(cmpSoftware,SWT.WRAP).setText("VMware SDK API : " + host.getAPI());
			new Label(cmpSoftware,SWT.WRAP).setText("License : " + host.getLicense());
			
			ExpandItem itSoftwareInfo = new ExpandItem (barSystem, SWT.NONE, 0);
			itSoftwareInfo.setText("Software Information");
			itSoftwareInfo.setHeight(cmpSoftware.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			itSoftwareInfo.setControl(cmpSoftware);
			
			Composite cmpCommands = new Composite(barSystem, SWT.NONE);
			lytGrid = new GridLayout();
			lytGrid.marginLeft = 30;
			lytGrid.marginTop = lytGrid.marginRight = lytGrid.marginBottom = 2;
			lytGrid.numColumns = 2;
			cmpCommands.setLayout(lytGrid);
			
			Label lblMaintenanceMode = new Label(cmpCommands, SWT.NONE);
			lblMaintenanceMode.setImage(VSManager.maintenanceMode);
			Link lnkMaintenanceMode = new Link(cmpCommands, SWT.NONE);
			lnkMaintenanceMode.setText("<A>Enter Maintenance Mode</A>");
			// TODO This link should allow user to set host in Maintenance Mode.
			
			ExpandItem itCommands = new ExpandItem (barSystem, SWT.NONE, 0);
			itCommands.setText("Commands");
			itCommands.setHeight(cmpCommands.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			itCommands.setControl(cmpCommands);
			
			ExpandBar barResources = new ExpandBar(cmpHost, SWT.NONE);
			grd = new GridData();
			grd.widthHint = (cmpHost.getBounds().width - 15) / 2;
			grd.heightHint = cmpHost.getBounds().height * 2 / 3;
			grd.verticalAlignment = SWT.TOP;
			barResources.setLayoutData(grd);
			
			final Composite cmpUsage = new Composite(barResources, SWT.NONE);
			lytGrid = new GridLayout ();
			lytGrid.numColumns = 2;
			lytGrid.marginLeft = 30;
			lytGrid.marginTop = lytGrid.marginRight = lytGrid.marginBottom = 2;
			cmpUsage.setLayout(lytGrid);

			final Label lblCPUUsage = new Label(cmpUsage,SWT.WRAP);
			int CPUUsage = host.getCPUUsage();
			lblCPUUsage.setText("CPU Usage : " + CPUUsage + " MHz");
			new Label(cmpUsage,SWT.WRAP).setText("Capacity");
			final ProgressBar pbrCPUUsage = new ProgressBar(cmpUsage,SWT.SMOOTH);
			pbrCPUUsage.setMaximum((int)host.getCPUMax());
			pbrCPUUsage.setSelection(CPUUsage);
			new Label(cmpUsage,SWT.WRAP).setText(host.getCPUMax().toString() + " MHz");
			
			final Label lblMemoryUsage = new Label(cmpUsage,SWT.WRAP);
			int MemoryUsage = host.getMemoryUsage();
			lblMemoryUsage.setText("Memory Usage : " + MemoryUsage + " MB");
			new Label(cmpUsage,SWT.WRAP).setText("Capacity");
			final ProgressBar pbrMemoryUsage = new ProgressBar(cmpUsage,SWT.SMOOTH);
			pbrMemoryUsage.setMaximum((int)host.getMemoryMax());
			pbrMemoryUsage.setSelection(MemoryUsage);
			new Label(cmpUsage,SWT.WRAP).setText(host.getMemoryMax().toString() + " MB");
			
			final Thread thdUsage = new Thread() {
				public void run() {
					while (!cmpUsage.isDisposed()) {
						cmpUsage.getDisplay().asyncExec(new Runnable() {
							public void run() {
								int CPUUsage = host.getCPUUsage();
								lblCPUUsage.setText("CPU Usage : " + CPUUsage + " MHz");
								pbrCPUUsage.setSelection(CPUUsage);
								int MemoryUsage = host.getMemoryUsage();
								lblMemoryUsage.setText("Memory Usage : " + MemoryUsage + " MB");
								pbrMemoryUsage.setSelection(MemoryUsage);
							}
						});
						try {
							Thread.sleep(2500);
						} catch (InterruptedException e) {
							// TODO Z: Check why this should happen
							e.printStackTrace();
						}
					}
				}
			};
			thdUsage.start();
			
			String[] dsNames = null;
			try {
				dsNames = host.getDataStoreNames();
			} catch (InvalidProperty e) {
				// TODO Z: Check why this should happen
				e.printStackTrace();
			} catch (RuntimeFault e) {
				// TODO Z: Check why this should happen
				e.printStackTrace();
			} catch (RemoteException e) {
				// TODO Z: Check why this should happen
				e.printStackTrace();
			}
			Table tblDatastores = new Table(cmpUsage, SWT.SINGLE );
			TableColumn colDatastoreName = new TableColumn(tblDatastores, SWT.LEFT);
			colDatastoreName.setText("Name");
			TableColumn colDatastoreSize = new TableColumn(tblDatastores, SWT.LEFT);
			colDatastoreSize.setText("Size");
			TableColumn colDatastoreUsed = new TableColumn(tblDatastores, SWT.LEFT);
			colDatastoreUsed.setText("Used");
			tblDatastores.setHeaderVisible(true);
			for ( int i = 0; i < dsNames.length; i++ ) {
				TableItem titDatastore = new TableItem(tblDatastores, SWT.NONE);
				String[] dsData = new String[3];
				dsData[0] = dsNames[i];
				try {
					dsData[1] = ((Long)host.getDataStoreSize(dsData[0])).toString() + " GB";
					dsData[2] = ((Long)host.getDataStoreUsed(dsData[0])).toString() + " GB";
				} catch (InvalidProperty e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				} catch (RuntimeFault e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				} catch (RemoteException e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				} catch (DatastoreNotFoundException e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				}
				titDatastore.setText(dsData);
			}
			grd = new GridData();
			grd.horizontalSpan = 2;
			tblDatastores.setLayoutData(grd);
			for ( int i = 0; i < tblDatastores.getColumnCount(); i++ ) {
				tblDatastores.getColumn(i).pack();
			}
			
			String[] netNames = null;
			try {
				netNames = host.getNetworkNames();
			} catch (InvalidProperty e) {
				// TODO Z: Check why this should happen
				e.printStackTrace();
			} catch (RuntimeFault e) {
				// TODO Z: Check why this should happen
				e.printStackTrace();
			} catch (RemoteException e) {
				// TODO Z: Check why this should happen
				e.printStackTrace();
			}
			Table tblNetworks = new Table(cmpUsage, SWT.SINGLE );
			TableColumn colNetworkName = new TableColumn(tblNetworks, SWT.LEFT);
			colNetworkName.setText("Name");
			TableColumn colNetworkVMsCount = new TableColumn(tblNetworks, SWT.LEFT);
			colNetworkVMsCount.setText("Guests connected");
			tblNetworks.setHeaderVisible(true);
			for ( int i = 0; i < netNames.length; i++ ) {
				TableItem titNetwork = new TableItem(tblNetworks, SWT.NONE);
				String[] netData = new String[2];
				netData[0] = netNames[i];
				try {
					netData[1] = ((Integer)host.getNetworkVmsCount(netData[0])).toString();
				} catch (InvalidProperty e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				} catch (RuntimeFault e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				} catch (RemoteException e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				} catch (NetworkNotFoundException e) {
					// TODO Z: Check why this should happen
					e.printStackTrace();
				}
				titNetwork.setText(netData);
			}
			grd = new GridData();
			grd.horizontalSpan = 2;
			tblNetworks.setLayoutData(grd);
			for ( int i = 0; i < tblNetworks.getColumnCount(); i++ ) {
				tblNetworks.getColumn(i).pack();
			}
			
			ExpandItem itUsageInfo = new ExpandItem (barResources, SWT.NONE, 0);
			itUsageInfo.setText("Usage Information");
			itUsageInfo.setHeight(cmpUsage.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			itUsageInfo.setControl(cmpUsage);
			
			tbiLeaf.setControl(cmpHost);
			tbiLeaf.setImage(VSManager.host);
		} else if ( ((TreeItem) arg0.item).getData() instanceof Guest ) {
			final Guest guest = (Guest)leaf;
			
			Composite cmpGuest = new Composite(tbiLeaf.getParent(),SWT.NONE);
			cmpGuest.setSize(tbiLeaf.getParent().getBounds().width - 10, tbiLeaf.getParent().getBounds().height - 10);
			GridLayout lytGrid = new GridLayout();
			lytGrid.numColumns = 2;
			cmpGuest.setLayout(lytGrid);
			
			// TODO Here should be a lot of VM info
			
			ExpandBar barSystem = new ExpandBar(cmpGuest, SWT.NONE);
			GridData grd = new GridData();
			grd.widthHint = cmpGuest.getBounds().width / 2;
			grd.heightHint = cmpGuest.getBounds().height / 2;
			grd.verticalAlignment = SWT.TOP;
			barSystem.setLayoutData(grd);
			
			Composite cmpCommands = new Composite(barSystem, SWT.NONE);
			lytGrid = new GridLayout();
			lytGrid.marginLeft = 30;
			lytGrid.marginTop = lytGrid.marginRight = lytGrid.marginBottom = 2;
			lytGrid.numColumns = 2;
			cmpCommands.setLayout(lytGrid);
			
			if ( !guest.isPoweredOn() ) {
				Link lnkStartUp = new Link(cmpCommands, SWT.NONE);
				lnkStartUp.setText("<A>Start up</A>");
				lnkStartUp.addSelectionListener(new SelectionListener() {

					@Override
					public void widgetDefaultSelected(SelectionEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void widgetSelected(SelectionEvent arg0) {
						try {
							guest.start();
						} catch (VmConfigFault e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (TaskInProgress e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (FileFault e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InvalidState e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InsufficientResourcesFault e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (RuntimeFault e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (RemoteException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
				});
			} else {
				Link lnkShutdown = new Link(cmpCommands, SWT.NONE);
				lnkShutdown.setText("<A>Shutdown</A>");
			}
			
			ExpandItem itCommands = new ExpandItem (barSystem, SWT.NONE, 0);
			itCommands.setText("Commands");
			itCommands.setHeight(cmpCommands.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			itCommands.setControl(cmpCommands);
			
			tbiLeaf.setControl(cmpGuest);
			tbiLeaf.setImage(VSManager.guest);
			
		}
	}

}
